package main

import "fmt"
import "container/vector"

type LineBuffer struct {
    cursor int
    line vector.IntVector
}

func (lb *LineBuffer) jumpTo( col int ) {
    for col >= len(lb.line) { lb.line.Push( ' ' ) }
    lb.cursor = col
}

func (lb *LineBuffer) insert(char int) {
    lb.line.Insert( lb.cursor, char )
    lb.cursor += 1
}

func (lb *LineBuffer) delete() {
    lb.line.Delete( lb.cursor - 1 )
    lb.cursor -= 1
}

type EditBuffer struct {
    currentLine LineBuffer
    lineCursor int
    lines vector.StringVector
}

func (eb *EditBuffer) init() *EditBuffer {
    eb.lines.Push( "" )
    return eb
}

func (eb *EditBuffer) InsertAll(chars string) *EditBuffer {
    for _, char := range chars { eb.Insert(char) }
    return eb
}

func (eb *EditBuffer) WriteAll( sink func( s string ) ) *EditBuffer {
    for i, line := range eb.lines {
        if i == eb.lineCursor {
            sink( string( []int( eb.currentLine.line ) ) )
        } else {
            sink( line )
        }
    }
    return eb
}

func (eb *EditBuffer) Delete() *EditBuffer {
    if eb.currentLine.cursor == 0 {
    
    } else {
        eb.currentLine.delete()
    }
    return eb
}

func (eb *EditBuffer) Insert(char int) *EditBuffer {
    if char == '\n' {
        eb.lines[eb.lineCursor] = string( []int( eb.currentLine.line ) )
        eb.lineCursor += 1
        if eb.lineCursor >= len(eb.lines) { eb.lines.Push( "" ) }
        eb.currentLine.cursor = 0
        eb.currentLine.line = []int(eb.lines[eb.lineCursor])
    } else {
        eb.currentLine.insert(char)
    }
    return eb
}

func (eb *EditBuffer) jumpLine( line int ) {
    eb.lines[eb.lineCursor] = string( []int( eb.currentLine.line ) )
    eb.lineCursor = line
    eb.currentLine.line = []int(eb.lines[eb.lineCursor])
}

func (eb *EditBuffer) JumpTo(line, col int) {
    if line != eb.lineCursor { eb.jumpLine( line ) }
    eb.currentLine.jumpTo( col )
}

func NewEditBuffer() *EditBuffer {
    return new(EditBuffer).init()
}

func main() {
    fmt.Println( "five furry ferrets fetching" )
    eb := NewEditBuffer()
    eb.InsertAll( "bundlemen! bundlemen?" ).Delete().Insert('!').InsertAll( "\ndone.\n" )
    eb.WriteAll( func (s string) {fmt.Printf("%v\n", s)} )
    eb.JumpTo(0, 0)
    eb.InsertAll( "a bit more -- " );
    eb.WriteAll( func (s string) {fmt.Printf("%v\n", s)} )
}
